當撰寫顯示多個(例如:展示數百筆廣告)圖片的網頁時,效能與用戶體驗主要有以下課題:
例如公司開發了一隻產品,其功能讓使用者選擇多個品牌(例:肯德基,家樂福...),按下搜尋後顯示我們從資料查詢到這些廠商的廣告圖片,少則數十,多則數千。
這時如果我們可以每次載入100筆,並且只在使用者"將要"看到某張圖片時或者某張圖片"已經"出現在使用者的畫面上,才向server請求該圖片,如此一來便可以大幅提升網頁渲染的速度,同時節省client與server的負擔,關於這一點,可以請大家一同觀賞這篇好文。
基於上文範例,我們可以進一步思考,是不是可以利用IntersectionObserver
的特性,達到我們的第2個目標:在使用者看完目前的圖片時,載入後續的圖片。
因此解決方法的關鍵點在於當IntersectionObserver
監聽到目前最後一筆圖片出現在螢幕上時,除了要向server請求這張圖片外,還要向server請求並渲染後續的圖片。
為了達到這樣的目標,我們可以設定每次載入100筆圖片,並在生成每張圖片時為它添加data-id
屬性,值為它出現的順序(1,2,3,...),如此一來當IntersectionObserver
監聽圖片的data-id
值若為100的倍數,請求這張圖片同時調用請求後續圖片的函式。
this._observer = new IntersectionObserver((entries, observer) => {
const ins = this;
entries.forEach(e=>{
if(e.isIntersecting){
const container = e.target;
//圖片載入顯示時加一點特效
container.classList.add("fadeIn");
const img = container.querySelector("img");
img.setAttribute("src", img.dataset.url);
img.removeAttribute("data-url");
observer.unobserve(container);
//當圖片的data-id值為100的倍數時,呼叫向伺服器請求並渲染圖片的方法
//第二個條件可以選用,讓你控制每頁圖片的最大數量
if (container.dataset.id % 100 === 0 && container.dataset.id <= 400) {
ins.generateImg(100);
}
}
});
});
如此一來便可以達到我們設定的兩個目標,只載入使用者螢幕上的圖片以及批次載入圖片,而這一切都可以靠運用IntersectionObserver
達成,以下是我在codePen上對該方法的實踐,提供大家參考。